import 'package:dio/dio.dart';
import 'package:xws/helpers/as_t.dart';
import 'package:xws/models/baidu/baidu_token.dart';
import 'package:xws/models/baidu/goods_info.dart';
import 'package:xws/models/banner_obj.dart';
import 'package:xws/models/goods/goods_obj.dart';
import 'package:xws/models/notify/chat_msg_obj.dart';
import 'package:xws/models/notify/chat_obj.dart';
import 'package:xws/models/notify/sys_notify.dart';
import 'package:xws/models/res_obj.dart';
import 'package:xws/models/user/user_obj.dart';
import 'package:xws/ui/splash/splash_page.dart';
import 'package:xws/utils/app_util.dart';
import 'package:xws/utils/log_util.dart';
import 'package:xws/utils/storage_util.dart';
import 'package:xws/utils/tools_util.dart';

import 'basic.dart';

/// 响应结果
class _Response {
  _Response(this.code, this.data, this.headers);

  factory _Response.fromResponse(Response<Map<String, dynamic>> response) {
    return _Response(
      response.statusCode,
      asT<Map<String, dynamic>>(response.data),
      response.headers,
    );
  }

  late final int? code;
  late final Map<String, dynamic> data;
  late final Headers headers;
}

/// json处理
T _fromJson<T>(dynamic value) {
  try {
    if (value == null) return dynamic as T;
    final Map<String, dynamic> v = asSDMap(value);
    if (T == ResObj) return ResObj.fromJson(v) as T;

    if (T == GoodsObj) return GoodsObj.fromJson(v) as T;
    if (T == User) return User.fromJson(v) as T;
    if (T == ChatMegObj) return ChatMegObj.fromJson(v) as T;
    if (T == BaiduToken) return BaiduToken.fromJson(v) as T;
    if (T == GoodsInfo) return GoodsInfo.fromJson(v) as T;
    if (T == BannerObj) return BannerObj.fromJson(v) as T;
    if (T == ChatObj) return ChatObj.fromJson(v) as T;
    if (T == SysNotify) return SysNotify.fromJson(v) as T;

    return dynamic as T;
  } catch (e) {
    error('json处理出错:$e');
    return dynamic as T;
  }
}

/// 请求相关

/// api
const String _api = 'https://tianshi.guangguang100.com';

/// token
String? get _token => getV<String>('token');

/// header
Map<String, dynamic>? get _headers {
  if (_token == null) return null;
  warning('TOKEN:$_token');
  return <String, dynamic>{'Authorization': _token};
}

/// 请求封装
Future<_Response> _request({
  required String path,
  String method = 'post',
  Map<String, dynamic>? data,
  String? contentType,
  Map<String, dynamic>? headers,
  dynamic formData,
}) async {
  try {
    final Response<Map<String, dynamic>> response = method == 'put'
        ? await put<Map<String, dynamic>>(
            url: _api + path,
            data: data,
            contentType: contentType,
            headers: headers,
            formData: formData,
          )
        : await request<Map<String, dynamic>>(
            url: _api + path,
            method: method,
            data: data,
            contentType: contentType,
            headers: headers,
            formData: formData,
          );

    //检测token
    if (response.data?['code'] == 401) {
      //登录过期
      setV('token', null);
      await delayed(const Duration(milliseconds: 800));
      pushWithoutContext(const SplashPage(), remove: true);
    }

    return _Response.fromResponse(response);
  } catch (e) {
    rethrow;
  }
}

///获取对象
Future<T?> getObj<T>(
  String path, {
  String method = 'post',
  Map<String, dynamic>? data,
  String? contentType,
  dynamic formData,
}) async {
  try {
    final _Response r = await _request(
      path: path,
      method: method,
      data: data,
      headers: _headers,
      contentType: contentType,
      formData: formData,
    );

    if (r.code == 200) return _fromJson<T>(r.data);
  } catch (e) {
    return null;
  }
}

/// 获取列表
Future<List<T>> getList<T>(
  String path, {
  Map<String, dynamic>? data,
  String dataKey = 'data',
  String method = 'post',
  String? contentType,
}) async {
  try {
    final ResObj? r = await getObj<ResObj>(
      path,
      method: method,
      data: data,
      contentType: contentType,
    );

    if (r != null && r.success) {
      return Stream<dynamic>.fromIterable(
        (dataKey.isEmpty ? r.data : r.data[dataKey]) as List<dynamic>? ?? <dynamic>[],
      ).map((dynamic d) => _fromJson<T>(d)).toList();
    }

    return <T>[];
  } catch (e) {
    et('网络错误');
    rethrow;
  }
}
